package com.funny.stock.trade.service;

import com.funny.stock.base.util.PropertiesCopyUtil;
import com.funny.stock.data.vo.StockConstants;
import com.funny.stock.trade.dao.pojo.GridTradePlanDO;
import com.funny.stock.trade.dao.pojo.GridTradePlanVarDO;
import com.funny.stock.trade.dao.repo.GridTradePlanRepo;
import com.funny.stock.trade.util.PriceUtils;
import com.funny.stock.trade.vo.GridTradePlanVO;
import com.funny.stock.trade.vo.PlanStatus;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;


/**
 *网格交易计划服务
 *
 * @author pengl
 * @date 2020/11/18
 */
@Component
public class GridTradePlanServiceImpl implements GridTradePlanService {
    private static final Logger logger = LoggerFactory.getLogger(GridTradePlanServiceImpl.class);

    @Autowired
    GridTradePlanRepo repository;

    @Autowired
    GridTradePlanVarService gridTradePlanVarService;


    @Cacheable(value = StockConstants.KEY_GRID_TRADE_POOL_LIST, unless= "#result.size() == 0")
    @Override
    public List<GridTradePlanVO> queryTradingPlanList() {
        logger.info("queryTradingPlanList");

        List<GridTradePlanDO> list = repository.findByStatusEquals(PlanStatus.TRADING.getStatus());
        return PropertiesCopyUtil.copyPropertiesByList(list, GridTradePlanVO.class);
    }

    @Override
    public List<GridTradePlanVO> queryTradePlanList(Integer personId, Long composeId) {
        List<GridTradePlanDO> list = repository.findByCreateIdAndComposeIdAndIsDelete(personId.longValue(), composeId,0);
        return PropertiesCopyUtil.copyPropertiesByList(list, GridTradePlanVO.class);
    }

    @Caching(
            put = {@CachePut(value = StockConstants.KEY_GRID_TRADE_POOL, key = "#result.id", condition = "#result != null ")},
            evict = {@CacheEvict(value = StockConstants.KEY_GRID_TRADE_POOL_LIST, allEntries = true, condition = "#result != null")}
    )
    @Override
    @Transactional
    public GridTradePlanVO add(GridTradePlanVO object) {
        logger.info("add:{}",object.getStockCode());
        object.setIsDelete(0);
        object.setStatus(PlanStatus.CONFIG.getStatus());
        GridTradePlanDO saveDO = PropertiesCopyUtil.copyProperties(object, GridTradePlanDO.class);
        GridTradePlanDO planDO = repository.save(saveDO);
        object.setId(planDO.getId());

        GridTradePlanVarDO planVarDO = new GridTradePlanVarDO();
        planVarDO.setPlanId(planDO.getId());
        List<BigDecimal> priceList = PriceUtils.calcNextTradePriceList(planDO.getBasePrice(), planDO.getIncreasePer(), planDO.getDecreasePer());
        planVarDO.setNextBuyPrice(priceList.get(0));
        planVarDO.setNextSellPrice(priceList.get(1));
        planVarDO.setUpdateTime(new Date());
        gridTradePlanVarService.savePlan(planVarDO);

        return object;
    }



    @Cacheable(value = StockConstants.KEY_GRID_TRADE_POOL, key = "#id", unless="#result == null")
    @Override
    public GridTradePlanVO findByIdAndCreateId(Long id,Long createId) {
        GridTradePlanDO planDO = repository.findByIdAndCreateId(id, createId);
        GridTradePlanVO planVO = PropertiesCopyUtil.copyProperties(planDO, GridTradePlanVO.class);
        return planVO;
    }

    @Caching(
            put = {@CachePut(value = StockConstants.KEY_GRID_TRADE_POOL, key = "#id", condition = "#result != null")},
            evict = {@CacheEvict(value = StockConstants.KEY_GRID_TRADE_POOL_LIST, allEntries = true, condition = "#result != null")}
    )
    @Transactional
    @Override
    public GridTradePlanVO startPlan(Long id, Integer personId) {
        GridTradePlanDO planDO = repository.findByIdAndCreateId(id, Long.valueOf(personId));
        if(planDO == null || planDO.getIsDelete() == 1) return null;

        planDO.setStatus(PlanStatus.TRADING.getStatus());

        planDO.setUpdateId(Long.valueOf(personId));
        planDO.setUpdateTime(new Date());
        planDO = repository.save(planDO);

        GridTradePlanVarDO planVarDO = new GridTradePlanVarDO();
        planVarDO.setPlanId(planDO.getId());
        List<BigDecimal> priceList = PriceUtils.calcNextTradePriceList(planDO.getBasePrice(), planDO.getIncreasePer(), planDO.getDecreasePer());
        planVarDO.setNextBuyPrice(priceList.get(0));
        planVarDO.setNextSellPrice(priceList.get(1));
        planVarDO.setUpdateTime(new Date());
        gridTradePlanVarService.savePlan(planVarDO);

        GridTradePlanVO planVO = PropertiesCopyUtil.copyProperties(planDO, GridTradePlanVO.class);
        return planVO;
    }

    @Caching(evict = {
            @CacheEvict(value = StockConstants.KEY_GRID_TRADE_POOL, key = "#id", condition = "#result != null "),
            @CacheEvict(value = StockConstants.KEY_GRID_TRADE_POOL_LIST, allEntries = true, condition = "#result != null ")
    })
    @Transactional
    @Override
    public GridTradePlanVO stopPlan(Long id, Integer personId) {
        GridTradePlanDO planDO = repository.findByIdAndCreateId(id, Long.valueOf(personId));
        if(planDO == null || planDO.getIsDelete() == 1) return null;

        planDO.setStatus(PlanStatus.STOP.getStatus());

        planDO.setUpdateId(Long.valueOf(personId));
        planDO.setUpdateTime(new Date());
        planDO = repository.save(planDO);

        GridTradePlanVO planVO = PropertiesCopyUtil.copyProperties(planDO, GridTradePlanVO.class);
        return planVO;
    }

    @Caching(evict = {
            @CacheEvict(value = StockConstants.KEY_GRID_TRADE_POOL, key = "#id", condition = "#result != null "),
            @CacheEvict(value = StockConstants.KEY_GRID_TRADE_POOL_LIST, allEntries = true, condition = "#result != null ")
    })
    @Override
    @Transactional
    public GridTradePlanVO remove(Long id,Integer personId) {
        GridTradePlanDO planDO = repository.findByIdAndCreateId(id, Long.valueOf(personId));
        if(planDO == null || planDO.getIsDelete() == 1) return null;

        planDO.setIsDelete(1);
        planDO.setStatus(PlanStatus.STOP.getStatus());

        planDO.setUpdateId(Long.valueOf(personId));
        planDO.setUpdateTime(new Date());
        planDO = repository.save(planDO);

        GridTradePlanVO planVO = PropertiesCopyUtil.copyProperties(planDO, GridTradePlanVO.class);
        return planVO;
    }
}
